#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using SqEngine.Audio;
using sqengine.Engine.Common;
using SqEngine;
using sqengine.Components;
using System.Reflection;
using TomShane.Neoforce.Controls;

#endregion





namespace sqengine.Components
{

    public class GUIComponent : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Game _game;
        private AdvancedContent _adcontent;
        private Manager _manager;
        private int _state = 0;
        private string _background_img_file = "";
        private MouseEventHandler event_h;
        private Dictionary<string, MouseEventHandler> bnt_events = new Dictionary<string, MouseEventHandler>();
        private string _version = SqEngine.SqEngineInfo._name + " " + SqEngine.SqEngineInfo._version;

        private List<string> _map_list = new List<string>();
        private List<string> _dirlist = new List<string>();

        private ListBox dir_list;
        private ListBox file_list;
        private Label lbl_path;
        private string input_result;

        public string GetInputBoxResult { get { return input_result; } }



        int bbWidth, bbHeight;

        private struct GUIDefault
        {
            // Buttons
            public static int bnt_w = 100;
            public static int bnt_h = 30;


            //MessageBox
            public static int dlg_w = 310;
            public static int dlg_h = 150;

            //Main form 
            public static int main_w = 400;
            public static int main_h = 300;
            public static int main_bnt_w = 200;
            public static int main_bnt_h = 30;
            public static int main_bnt_spacing = 10;

            //File Dialog
            public static int opendlg_w = 570;
            public static int opendlg_h = 370;

        }


        public GUIComponent(Game game, AdvancedContent adcontent, Manager manager, string back_image)
            : base(game)
        {
            _game = game;
            _manager = manager;
            _adcontent = adcontent;
            _manager.Visible = false;
            _background_img_file = back_image;
            _manager.SkinDirectory = _adcontent.ContentRoot + "/Textures/UI/Skins/";

        }

        private void GraphicsDevice_DeviceReset(object sender, System.EventArgs e)
        {
            bbWidth = GraphicsDevice.PresentationParameters.BackBufferWidth;
            bbHeight = GraphicsDevice.PresentationParameters.BackBufferHeight;
        }

        protected override void LoadContent()
        {
            this._game.GraphicsDevice.DeviceReset += new System.EventHandler(GraphicsDevice_DeviceReset);

            base.LoadContent();
        }


        public override void Initialize()
        {
            SetupButtons();
            base.Initialize();
        }


        private void SetupButtons()
        {
            bnt_events.Add("Return to game", SelfClose_Click);
            bnt_events.Add("Load map", bnt_loadmap_Click);
            bnt_events.Add("Options", null);
            bnt_events.Add("Exit", bnt_exit_Click);
        }

        public override void Draw(GameTime gameTime)
        {

            base.Draw(gameTime);
        }

        public bool Active()
        {
            return _manager.Visible;
        }

        public override void Update(GameTime gameTime)
        {



            if (_manager.Visible)
            {
                _manager.DrawOrder = 1;
            }


            base.Update(gameTime);
        }
        private Window AddWindow(Manager manager, string caption, int width, int height, bool closebuttonvisible, int left, int top, bool movable)
        {
            Window _tmp = new Window(manager);
            _tmp.Init();
            _tmp.Width = width;
            _tmp.Height = height;
            _tmp.Text = caption;
            _tmp.Resizable = false;
            _tmp.Movable = movable;

            if (left == -1 && top == -1)
            {
                _tmp.Center();
            }
            else
            {
                _tmp.Width = width;
                _tmp.Height = height;
            }

            _tmp.Visible = true;
            _tmp.CloseButtonVisible = closebuttonvisible;

            return _tmp;
        }

        private Label AddLabel(Manager manager, Control parent, string text, int width, int height, int left, int top)
        {
            Label _tmp;

            _tmp = new Label(manager);
            _tmp.Init();
            _tmp.Parent = parent;
            _tmp.Text = text;
            _tmp.Width = width;
            _tmp.Height = height;
            _tmp.Left = left;
            _tmp.Top = top;

            return _tmp;

        }

        private Button AddButton(Manager manager, Control parent, string text, int width, int height, int left, int top, Anchors anchor, ref MouseEventHandler OnMouseClick)
        {
            Button _tmp = new Button(manager);

            _tmp.Text = text;
            _tmp.Init();
            _tmp.Parent = parent;
            _tmp.Anchor = anchor;
            _tmp.Width = width;
            _tmp.Height = height;
            _tmp.Left = left;
            _tmp.Top = top;

            if (OnMouseClick != null)
                _tmp.Click += new MouseEventHandler(OnMouseClick);

            return _tmp;
        }

        private ListBox AddListbox(Manager manager, Control parent, int width, int height, int left, int top, Anchors anchor)
        {
            ListBox _tmp = new ListBox(manager);

            _tmp.Init();
            _tmp.Parent = parent;
            _tmp.Anchor = anchor;
            _tmp.Height = height;
            _tmp.Width = width;
            _tmp.Left = left;
            _tmp.Top = top;
            return _tmp;

        }

        private TextBox AddTextBox(Manager manager, Control parent, int width, int height, int left, int top, Anchors anchor)
        {
            TextBox _tmp = new TextBox(manager);
            _tmp.Init();
            _tmp.Anchor = anchor;
            _tmp.Height = height;
            _tmp.Width = width;
            _tmp.Left = left;
            _tmp.Top = top;
            return _tmp;
        }


        public void MessageDlg(string caption, string text, ref MouseEventHandler OnYesClick, ref MouseEventHandler OnNoClick)
        {
            Button bnt_yes;
            Button bnt_no;
            Label lbl_text;

            Window dlg_wnd;

            _manager.Visible = true;
            _state = 1;

            dlg_wnd = AddWindow(_manager, caption, GUIDefault.dlg_w, GUIDefault.dlg_h, false, -1, -1, false);
            lbl_text = AddLabel(_manager, dlg_wnd, text, dlg_wnd.Width - 20, 15, 2, 10);
            event_h = OnNoClick;
            bnt_no = AddButton(_manager, dlg_wnd, "No", GUIDefault.bnt_w, GUIDefault.bnt_h, dlg_wnd.Width - (GUIDefault.bnt_w) - 18, 50, Anchors.None, ref event_h);
            event_h = OnYesClick;
            bnt_yes = AddButton(_manager, dlg_wnd, "Yes", GUIDefault.bnt_w, GUIDefault.bnt_h, 10, 50, Anchors.Left, ref event_h);

            _manager.Add(dlg_wnd);
            dlg_wnd.ShowModal();
        }

        public void ShowMain()
        {
            if (!_manager.Visible)
            {

                Window dlg_wnd;
                int bnt_count = 0;
                _manager.Visible = true;
                _state = 1;

                dlg_wnd = AddWindow(_manager, string.Format("Main menu :: [{0}]", _version), GUIDefault.main_w, GUIDefault.main_h, false, -1, -1, false);
                dlg_wnd.Closed += new WindowClosedEventHandler(window_Closed);

                // Enumerate buttons and events
                foreach (KeyValuePair<string, MouseEventHandler> kvp in bnt_events)
                {
                    string aa = (GUIDefault.main_bnt_spacing + (GUIDefault.main_bnt_h * bnt_count)).ToString();
                    MouseEventHandler event_h = kvp.Value;

                    Button _bnt = AddButton(_manager, dlg_wnd, kvp.Key, GUIDefault.main_bnt_w, GUIDefault.main_bnt_h, (dlg_wnd.Width / 2) - (GUIDefault.main_bnt_w / 2), GUIDefault.main_bnt_spacing + (GUIDefault.main_bnt_h * bnt_count) + GUIDefault.main_bnt_spacing * bnt_count, Anchors.None, ref event_h);
                    bnt_count++;
                }

                _manager.Add(dlg_wnd);
                dlg_wnd.ShowModal();

            }

        }


        public void InputBox(string caption, string text, ref MouseEventHandler OnBntClick)
        {
           
            Window dlg_wnd;
            dlg_wnd = AddWindow(_manager, caption, GUIDefault.opendlg_w, GUIDefault.opendlg_h, false, -1, -1, true);

            Label lbl_text = AddLabel(_manager, dlg_wnd, text, GUIDefault.opendlg_w - 30, 10, 10, 10);
            TextBox edt_input = AddTextBox(_manager, dlg_wnd, 200, 30, 10, 20, Anchors.None);
            edt_input.KeyPress += new KeyEventHandler(edt_input_KeyPress);
            
            event_h = OnBntClick;

            Button bnt_Select = AddButton(_manager, dlg_wnd, "OK", GUIDefault.bnt_w, GUIDefault.bnt_h, 10, 10, Anchors.None, ref event_h);

            dlg_wnd.ShowModal();
                
        }

        void edt_input_KeyPress(object sender, KeyEventArgs e)
        {
            if (e.Key == Keys.Enter)
            {
                input_result = ((TextBox)sender).Text;
            }
        
        }


        public void FileOpenDialog(string caption, string text, string directory, string file_ext)
        {
            Window dlg_wnd;

            dlg_wnd = AddWindow(_manager, caption, GUIDefault.opendlg_w, GUIDefault.opendlg_h, false, -1, -1, true);


            _dirlist = Functions.GetDirectoryList(directory);
            lbl_path = AddLabel(_manager, dlg_wnd, directory, GUIDefault.opendlg_w - 30, 10, 15, 285);

            Label lbl_text = AddLabel(_manager, dlg_wnd, text, GUIDefault.opendlg_w - 30, 10, 10, 10);


            dir_list = AddListbox(_manager, dlg_wnd, GUIDefault.opendlg_w / 2 - 20, 250, 10, 30, Anchors.None);
            dir_list.ItemIndexChanged += new TomShane.Neoforce.Controls.EventHandler(dir_list_change);
            dir_list.ItemIndex = 0;
            dir_list.DoubleClick += new MouseEventHandler(dir_list_DoubleClick);
            dir_list = AddItemToListBox(_dirlist, dir_list);

            _map_list = Functions.GetFilesList(directory);
            file_list = AddListbox(_manager, dlg_wnd, GUIDefault.opendlg_w / 2 - 20, 250, dir_list.Width + 10, 30, Anchors.None);
            file_list = AddItemToListBox(_map_list, file_list);


            event_h = SelfClose_Click;
            Button bnt_cancel = AddButton(_manager, dlg_wnd, "Cancel", GUIDefault.bnt_w, GUIDefault.bnt_h, dlg_wnd.Width - GUIDefault.bnt_w - 30, dir_list.Height + GUIDefault.bnt_h + 20, Anchors.None, ref event_h);
            event_h = bnt_Select_Click;
            Button bnt_Select = AddButton(_manager, dlg_wnd, "Select", GUIDefault.bnt_w, GUIDefault.bnt_h, 10, dir_list.Height + GUIDefault.bnt_h + 20, Anchors.None, ref event_h);
            file_list.DoubleClick += new MouseEventHandler(bnt_Select_Click);
            _manager.Add(dlg_wnd);

            dlg_wnd.ShowModal();

        }

        void bnt_Select_Click(object sender, MouseEventArgs e)
        {
            if (file_list.ItemIndex != -1)
            {
                string filetoload = lbl_path.Text + file_list.Items[file_list.ItemIndex].ToString();
                filetoload = filetoload.Replace("\\\\", "\\");

                ((sqengine)_game).SetMapToLoad(filetoload);
                ((sqengine)_game).PrepareCleanMapThread();
            }

        }

        void dir_list_DoubleClick(object sender, MouseEventArgs e)
        {

            if (dir_list.Items[dir_list.ItemIndex].ToString() == "..")
            {
                string path = Directory.GetParent(lbl_path.Text).ToString();
                if (path != null)
                {
                    lbl_path.Text = path;
                    _dirlist = Functions.GetDirectoryList(lbl_path.Text);
                    dir_list.Items.Clear();
                    dir_list.Items.Add("..");
                    dir_list = AddItemToListBox(_dirlist, dir_list);
                }
            }
            else
            {
                _dirlist.Clear();
                _dirlist = Functions.GetDirectoryList(lbl_path.Text + "\\" + dir_list.Items[dir_list.ItemIndex].ToString());
                lbl_path.Text = lbl_path.Text + "\\" + dir_list.Items[dir_list.ItemIndex].ToString();
                dir_list.Items.Clear();
                dir_list.Items.Add("..");
                dir_list = AddItemToListBox(_dirlist, dir_list);
            }

            dir_list_change(sender, e);
        }

        void dir_list_change(object sender, TomShane.Neoforce.Controls.EventArgs e)
        {
            if (dir_list.ItemIndex != -1)
            {
                _map_list.Clear();
                _map_list = Functions.GetFilesList(lbl_path.Text + "\\" + dir_list.Items[dir_list.ItemIndex].ToString());
                file_list.Items.Clear();
                file_list = AddItemToListBox(_map_list, file_list);
                //_dirlist = Functions.GetDirectoryList(dir_list.Items[dir_list.ItemIndex].ToString());
            }
        }

        private ListBox AddItemToListBox(List<string> list, ListBox listbox)
        {
            foreach (string item in list)
            {
                listbox.Items.Add(item);
            }

            return listbox;
        }


        void bnt_exit_Click(object sender, MouseEventArgs e)
        {
            MouseEventHandler _onselfclose = new MouseEventHandler(SelfClose_Click);
            MouseEventHandler _exitclick = new MouseEventHandler(Exit_Click);

            MessageDlg(_version, "Are you sure you want to exit?", ref _exitclick, ref _onselfclose);
        }

        void bnt_loadmap_Click(object sender, MouseEventArgs e)
        {
            FileOpenDialog("Load map :: " + _version, "Select map file", "c:\\", "*.sqmap");
        }


        void window_Closed(object sender, WindowClosedEventArgs e)
        {
            _manager.Visible = false;
            _state = 2;
        }

        void Exit_Click(object sender, MouseEventArgs e)
        {
            _game.Exit();

        }

        void SelfClose_Click(object sender, MouseEventArgs e)
        {
            if (sender is Button)
                (((Window)((ClipBox)(((Button)sender).Parent)).Parent)).Close();
        }
    }
}